package net.flowas.genericcrud.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import net.flowas.genericcrud.CrudType;
import net.flowas.genericcrud.RepositoryService;
import net.flowas.genericcrud.dto.PageModdel;
import net.flowas.genericcrud.dto.QueryOption;

public class MybatisRepositoryService implements RepositoryService{
	private SqlSession sqlSession;
	private String resource = "mybatis-config.xml";
	
	public void setSqlSession(SqlSession sqlSession) {
		this.sqlSession = sqlSession;
	}

	public void init() {
		if(sqlSession==null) {
			try {
				InputStream inputStream = Resources.getResourceAsStream(resource);
				SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
				sqlSession = sqlSessionFactory.openSession();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
	
	@Override
	public Long count(QueryOption<Map<String, Object>> option, Class type) {
		Map<String, Object> conditions=option.getExample();
		return sqlSession.selectOne(getSqlName(type,CrudType.COUNT),conditions);
	}

	@Override
	public <T> List<T> findRang(QueryOption<Map<String, Object>> option, Class<T> type) {
		Map<String, Object> conditions=option.getExample();
		return sqlSession.selectList(getSqlName(type,CrudType.QUERY),conditions);
	}

	@Override
	public Object saveOrUpdate(Object entity) {
		sqlSession.insert(getSqlName(entity.getClass(),CrudType.COUNT), entity);
		return null;
	}

	@Override
	public void remove(Class type, Object id) {
		sqlSession.delete(getSqlName(type,CrudType.COUNT), id);
	}

	@Override
	public <T> T findById(Class<T> type, Object t) {
		return sqlSession.selectOne(getSqlName(type,CrudType.GET),t);
	}

	@Override
	public void detach(Object entity) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Collection<Class<? extends Serializable>> getHandledTypes() {
		Collection<Class<? extends Serializable>> list = new ArrayList<>();
		//list.add(ProductDto.class);
		return list;
	}
	/**
	 * 统一约定sql语句的命名规则
	 * @param type
	 * @param crudType
	 * @return
	 */
	private String getSqlName(Class type, CrudType crudType) {
		return type.getSimpleName()+"_"+crudType.name();
	}

	@Override
	public <T> PageModdel<T> queryWithCount(QueryOption<Map<String, Object>> option, Class<T> type) {
		PageModdel<T> page = new PageModdel<>();	
		page.setTotal(count(option, type));
		page.setRows(findRang(option, type));
		return page;
	}
}
